package Client.Net;

import java.net.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;

/**
 * Client Factory Object dat ervoor zorgt dat er een verbinding naar een 
 * RMI-server kan worden gemaakt.
 */
public class ClientFactory //implements IRemoteCallbackHandler
{
    //TODO: javadocs
    public final static int DefaultPort = 2005; //Registry.REGISTRY_PORT;
    private String m_Host;
    private int m_Port;
    private transient Registry m_Reg;

    /**
     * Constructor die een nieuwe client aanmaakt.
     * @param host
     * @param port
     * @throws RemoteException 
     */
    public ClientFactory(String host, int port)
            throws RemoteException
    {
        m_Host = host;
        m_Port = port;
        m_Reg = LocateRegistry.getRegistry(host, port);
    }

    /**
     * Zorgt ervoor dat een object dynamisch naar een RemoteObject wordt gemaakt.
     * @param obj
     * @throws RemoteException 
     */
    public void MakeRemote(Remote obj, boolean force)
        throws RemoteException
    {
	try
	{
	    UnicastRemoteObject.unexportObject(obj, true);
	}
	catch (Exception ex)
	{
	    // Object wasn't exported yet.
	}
        UnicastRemoteObject.exportObject(obj, 0);
    }

    /**
     * Geeft de url terug (combinatie host-port)
     * @return url
     */
    public String getUrl()
    {
        return "//" + m_Host  + ":" + m_Port;
    }

    /**
     * Geeft de complete RMI-url terug
     * @return complete RMI-url
     */
    public String getCompleteUrl()
    {
        return "rmi:" + getUrl();
    }

    /**
     * Geeft een lijst van de beschikbare remote instances.
     * @return remote instances
     * @throws RemoteException Remote Error
     * @throws MalformedURLException Url Error
     */
    public String[] GetRemoteInstances()
            throws RemoteException, MalformedURLException
    {
        //return Naming.list(getCompleteUrl());
        return m_Reg.list();
    }

    /*
     * Dit is een Wrapper voor RMI Objecten te creeeren.
     * @param name = naam object
     * @param returnvalue = RMI Object (typecasted to returntype).
     * @throws RemoteException Remote Error
     * @throws NotBoundException Verbinding Error
     * @throws Exception Generieke Error
     */
    public <T> T GetRemoteInstance(String name)
            throws RemoteException, NotBoundException, Exception
    {
        // voorbeeld: (Bank)Naming.lookup(getCompleteUrl() + "/" + "Bank")
        //return (T)Naming.lookup(getCompleteUrl() + "/" + name);
        return (T)m_Reg.lookup(name);
    }
    
    public void dispose()
    {
        //TODO: [CLIENT#02] [CHECK] disposal m_Reg (Close connection)
        // RMI sluit automatisch af d.m.v. een timeout in de connectie.
        // De vraag echter is of dit ook gebeurt als er geen communicatie
        // meer over de lijn nodig is.
        m_Reg = null;
    }

    //public boolean OnCallback(String name, RemoteObject object)
    //{
    //    //TODO: [CLIENT] [IMPLEMENT] pass name, object to gui
    //}
}
